/**
 * 语音合成模块类，负责处理在线语音合成的相关操作。
 *
 * @author linxiongjun
 * @date 2025-05-29
 */
package com.asr.plugin_asr

import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import com.asr.plugin_asr.ktx.log
import com.asr.plugin_asr.params.TTSParams
import com.iflytek.sparkchain.core.tts.OnlineTTS
import com.iflytek.sparkchain.core.tts.TTS
import com.iflytek.sparkchain.core.tts.TTSCallbacks

/**
 * 语音合成类，封装了讯飞在线语音合成的初始化、启动和停止功能。
 */
class SpeechSynthesis {
    // 讯飞在线TTS实例
    private var onlineTTS: OnlineTTS? = null

    // TTS参数配置
    private val tTSParams = TTSParams()

    // 是否正在播放音频
    private var isPlaying = false

    // AudioTrack实例，用于播放音频数据
    private var audioTrack: AudioTrack? = null

    // 音频通道配置：单声道
    private val channelConfig: Int = AudioFormat.CHANNEL_OUT_MONO

    // 音频编码格式：PCM 16位
    private val audioFormat: Int = AudioFormat.ENCODING_PCM_16BIT

    /**
     * 开始在线语音合成并播放音频。
     *
     * @param text 要合成的文本
     * @return 合成结果，0表示成功，非0表示失败
     */
    fun startOnlineTTS(text: String): Int {
        // 如果正在播放音频，则先停止
        if (isPlaying) {
            stop()
        }

        // 初始化AudioTrack，用于播放音频数据
        initAudioTrack()

        // 初始化OnlineTTS实例，并设置参数
        onlineTTS = OnlineTTS(tTSParams.vcn).apply {
            aue(tTSParams.aue)
            auf(tTSParams.auf)
            speed(tTSParams.speed)
            pitch(tTSParams.pitch)
            volume(tTSParams.volume)
            bgs(0) // 设置背景音（0表示无背景音）

            // 注册TTS回调函数
            registerCallbacks(object : TTSCallbacks {
                /**
                 * 合成结果回调
                 *
                 * @param result 合成结果对象
                 * @param p1 额外参数（通常为null）
                 */
                override fun onResult(result: TTS.TTSResult?, p1: Any?) {
                    result?.data?.let { audioData ->
                        if (audioTrack != null && audioData.isNotEmpty()) {
                            audioTrack!!.write(audioData, 0, audioData.size)
                        }
                    }

                    result?.status?.let { status ->
                        if (status == 2) {
                            // 音频合成回调结束状态
                            "音频合成成功".log()
                            stopAudioTrack()
                        }
                    }
                }

                /**
                 * 错误回调
                 *
                 * @param error 错误对象
                 * @param p1 额外参数（通常为null）
                 */
                override fun onError(error: TTS.TTSError, p1: Any?) {
                    val msg = "合成出错！code:${error.code},msg:${error.errMsg},sid:${error.sid}"
                    msg.log()
                    stopAudioTrack()
                }
            })
        }

        // 开始语音合成
        val ret = onlineTTS!!.aRun(text)
        if (ret == 0) {
            isPlaying = true
        }
        return ret
    }

    /**
     * 初始化AudioTrack
     */
    private fun initAudioTrack() {
        if (audioTrack == null) {
            val minBufferSize = AudioTrack.getMinBufferSize(
                tTSParams.rate,
                channelConfig,
                audioFormat
            )
            audioTrack = AudioTrack(
                AudioManager.STREAM_MUSIC, // 音频流类型
                tTSParams.rate, // 采样率
                channelConfig, // 声道配置
                audioFormat, // 音频格式
                minBufferSize, // 缓冲区大小
                AudioTrack.MODE_STREAM // 流模式
            ).apply {
                play() // 开始播放
            }
        } else {
            audioTrack!!.play() // 如果已存在，则重新开始播放
        }
    }

    /**
     * 停止所有语音合成和音频播放。
     */
    fun stop() {
        stopOnlineTTS()
        stopAudioTrack()
    }

    /**
     * 停止在线语音合成。
     */
    private fun stopOnlineTTS() {
        onlineTTS?.let {
            it.stop()
            onlineTTS = null
        }
    }

    /**
     * 停止音频播放并释放资源。
     */
    private fun stopAudioTrack() {
        audioTrack?.let {
            it.stop()
            it.release()
            audioTrack = null
            isPlaying = false
        }
    }

    /**
     * 释放所有资源。
     */
    fun release() {
        stop()
        // 这里可以添加其他需要释放的资源
    }
}